﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
using Newtonsoft.Json;
using System;
using System.Buffers;
namespace Zeus.Mvc.Options
{
    using InputFormatters;
    using Loggers;
    using Loggers.Implementations;
    using Results;
    using Results.Implementations;
    public class ZeusMvcOptions
    {
        private readonly ILoggerFactory _loggerFactory;
        private readonly ArrayPool<char> _charArrayPool;
        private readonly ObjectPoolProvider _objectPoolProvider;

        private const string _defaultDateFormatString = "yyyy-MM-dd HH:mm:ss";

        public bool EnableCorrelationIdMiddleware {
            get; set;
        }

        public Type TypeOfIZeusResultExecutor {
            get; set;
        }

        public Type TypeOfIZeusResultFormatter {
            get; set;
        }

        public Type TypeOfIHttpContextLogger {
            get; set;
        }

        public JsonSerializerSettings JsonSerializerSettings {
            get; set;
        }

        public ZeusMvcOptions() : this(typeof(ZeusResultExecutor), typeof(RequestGuidZeusResultFormatter), typeof(HttpContextLogger), null)
        {

        }

        public ZeusMvcOptions(Type typeOfhttpContextLogger) : this(typeof(ZeusResultExecutor), typeof(RequestGuidZeusResultFormatter), typeOfhttpContextLogger, null)
        {

        }

        public ZeusMvcOptions(Type typeOfZeusResultExecutor, Type typeOfZeusResultFormatter) : this(typeOfZeusResultExecutor, typeOfZeusResultFormatter, typeof(HttpContextLogger), null)
        {

        }

        public ZeusMvcOptions(Type typeOfZeusResultExecutor, Type typeOfZeusResultFormatter, Type typeOfHttpContextLogger, JsonSerializerSettings jsonSerializerSettings)
        {
            EnableCorrelationIdMiddleware = true;
            if (typeOfZeusResultExecutor != null && !typeof(IZeusResultExecutor).IsAssignableFrom(typeOfZeusResultExecutor))
            {
                throw new ArgumentException($"IZeusResultExecutor implementation error");
            }
            if (typeOfZeusResultFormatter != null && !typeof(IZeusResultFormatter).IsAssignableFrom(typeOfZeusResultFormatter))
            {
                throw new ArgumentException($"IZeusResultFormatter implementation error");
            }
            if (typeOfHttpContextLogger != null && !typeof(IHttpContextLogger).IsAssignableFrom(typeOfHttpContextLogger))
            {
                throw new ArgumentException($"IHttpContextLogger implementation error");
            }
            TypeOfIZeusResultExecutor = typeOfZeusResultExecutor;
            TypeOfIZeusResultFormatter = typeOfZeusResultFormatter;
            TypeOfIHttpContextLogger = typeOfHttpContextLogger;
            JsonSerializerSettings = jsonSerializerSettings ?? new JsonSerializerSettings()
            {
                DateFormatString = _defaultDateFormatString
            };
        }

        public void Configure(MvcOptions options)
        {
            options.InputFormatters.Add(new ZeusInputFormatter(
                _charArrayPool,
                _objectPoolProvider,
                JsonSerializerSettings,
                _loggerFactory.CreateLogger<ZeusInputFormatter>()));
        }
    }
}
